package com.urick.statemachine;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.urick.statemachine.StateMachineAssert.assertTrue;

/**
 * Design Theories: 状态机，负责维护管理状态、事件、处理器
 * <a href=""></a>
 *
 * @author Rick 2023/4/4 16:08
 * Email: rickwork@163.com
 * Wechat: yy3076815642
 * QQ: 3076815642
 * @since 1.0
 */
public class StateMachine {
    private final Map<Object, StateMap> STATE_MAP = new ConcurrentHashMap<>();
    private volatile boolean init;

    /**
     * 从状态机中获取状态，触发状态流转
     *
     * @param context 当前上下文
     * @return 触发结果
     */
    public StateMachine trigger(IStateContext<?,?> context) {
        assertTrue(init, "Please init StateMap Machine");
        Object state = context.getState();
        assertTrue(STATE_MAP.containsKey(state), "This is not an state [" + state + "] in a state machine.");

        StateMap stateMapNode = STATE_MAP.get(state);
        Object event = context.getEvent();
        assertTrue(stateMapNode.contains(event), "This is not an event [" + event + "] of state [" + state + "]  in a state machine.");
        IStateProcess process = stateMapNode.getProcess(event);
        process.process(context);
        return this;
    }

    private static class StateMachineHolder {
        private static final StateMachine INSTANCE = new StateMachine();
    }

    public static StateMachine getInstance() {
        return StateMachineHolder.INSTANCE;
    }

    public StateMachine init(List<StateMap> nodeList) {
        nodeList.forEach(node -> {
            STATE_MAP.put(node.getCurrentState(), node);
        });
        init = true;
        return this;
    }
}
